/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package simulador;

import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.Color;

/**
 *
 * @author csantos
 */
public class RetaCarregada {

	private float a; // **
	private float b; // a*x + b*y + c = 0
	private float c; // **
	// Abaixo: constantes pre-calculadas para aliviar as contas no metodo de calculo
	// de forcas
	private float m; // Coeficiente angular desta reta
	private float mP; // Coeficiente angular da reta perpendicular a esta
	float[] p0;
	float[] p1;
	float largura;
	static float Ke = 0.5f; // constante eletrica
	static float distMin = 35f;
	static public float densidadeCarga = -0.1f;

	public RetaCarregada(float x0, float y0, float x1, float y1) {
		a = y0 - y1;
		b = x1 - x0;
		c = x0 * y1 - y0 * x1;

		// As extremidades da reta serao utilizadas mais adiante
		p0 = new float[2];
		p0[0] = x0;
		p0[1] = y0;
		p1 = new float[2];
		p1[0] = x1;
		p1[1] = y1;

		largura = (float) Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
		m = -a/b;
		mP = b/a;
	}

	public void setEnd(float x, float y) {
		a = p0[1] - y;
		b = x - p0[0];
		c = p0[0] * y - p0[1] * x;

		p1[0] = x;
		p1[1] = y;

		largura = (float) Math.sqrt((p1[0] - p0[0]) * (p1[0] - p0[0]) +
						(p1[1] - p0[1]) * (p1[1] - p0[1]));

		m = -a/b;
		mP = b/a;
	}

	static public void ajustarDensidadeReta(float densidade) {
		densidadeCarga = densidade;
	}

	public float distanciaPontoReta(float[] ponto) {
		return (float) Math.abs((a * ponto[0] + b * ponto[1] + c) / Math.sqrt(a * a + b * b));
	}

	public float[] forcaAoPonto(float[] ponto, float cargaPonto) {
		// Retorna o vetor forca ao ponto
		float[] forcasResultantes = {0f, 0f};

		// Forca resultante: Componente Y
		float dist = distanciaPontoReta(ponto);
		
		if(dist > distMin) return forcasResultantes;

		// Abaixo: Eixo X da projecao do ponto na reta em questao (usado pra saber se o ponto esta a direita ou esquerda da reta)
		float a2=a*a;
		float xProj = -(b*(-mP*ponto[0]+ponto[1])+c)/(a+b*mP);
		float yProj = (a2*ponto[1]-c-a*ponto[0])/(b+a2);

		float distProjP0;
		float distProjP1;
		if(p0[0] > xProj)
			distProjP0 = (float)Math.sqrt((xProj-p0[0])*(xProj-p0[0])+(yProj-p0[1])*(yProj-p0[1]));
		else
			distProjP0 = (float)-Math.sqrt((xProj-p0[0])*(xProj-p0[0])+(yProj-p0[1])*(yProj-p0[1]));

		if(p1[0] > xProj)
			distProjP1 = (float)Math.sqrt((xProj-p0[0])*(xProj-p0[0])+(yProj-p0[1])*(yProj-p0[1]));
		else
			distProjP1 = (float)-Math.sqrt((xProj-p0[0])*(xProj-p0[0])+(yProj-p0[1])*(yProj-p0[1]));

		float m2 = (m*m); // Coeficiente angular ao quadrado

		/*
		 * Forca resultante: Componente Y
		 */
		forcasResultantes[1] = cargaPonto * Ke * densidadeCarga * Math.abs(
						distProjP0 / (dist * (float) Math.sqrt(dist * dist + (distProjP0 * distProjP0 / 4f)))
						-
						distProjP1 / (dist * (float) Math.sqrt(dist * dist + (distProjP1 * distProjP1 / 4f)))
						);

		// Rotaciona o vetor para sua posicao natural
		float vetRotX, vetRotY;
		if(a == 0.0f) // reta y=c/b
		{
			if(ponto[1] < p0[1]) { // Ponto abaixo da reta
				vetRotX = 0.0f;
				vetRotY = 1.0f * forcasResultantes[1];
			}
			else { // Ponto acima da reta
				vetRotX = 0.0f;
				vetRotY = -1.0f * forcasResultantes[1];
			}
		}
		else if(b == 0.0f) // reta x=c/a
		{
			if(ponto[0] < p0[0]) { // Ponto a esquerda da reta
				vetRotX = 1.0f * forcasResultantes[1];
				vetRotY = 0.0f;
			}
			else { // Ponto a direita da reta
				vetRotX = -1.0f * forcasResultantes[1];
				vetRotY = 0.0f;
			}
		}
		else // angulo nao reto
		{
			if(m < 0)
			{
				if(xProj < ponto[0]) // Ponto a direita da reta
				{
					vetRotX = ((float) -Math.sqrt(m2 / (m2 + 1f))) * forcasResultantes[1];
					vetRotY = (float) -Math.sqrt(1f / (1f + m2)) * forcasResultantes[1];
				}
				else // ponto a esquerda da reta
				{
					vetRotX = ((float) Math.sqrt(m2 / (m2 + 1f))) * forcasResultantes[1];
					vetRotY = (float) Math.sqrt(1f / (1f + m2)) * forcasResultantes[1];
				}
			}
			else
			{
				if(xProj < ponto[0]) // Ponto a direita da reta
				{
					vetRotX = -((float) Math.sqrt(m2 / (m2 + 1f))) * forcasResultantes[1];
					vetRotY = (float) Math.sqrt(1f / (1f + m2)) * forcasResultantes[1];
				}
				else // ponto a esquerda da reta
				{
					vetRotX = ((float) Math.sqrt(m2 / (m2 + 1f))) * forcasResultantes[1];
					vetRotY = (float) -Math.sqrt(1f / (1f + m2)) * forcasResultantes[1];
				}
			}
		}

		forcasResultantes[0] = vetRotX;
		forcasResultantes[1] = vetRotY;

		return forcasResultantes;
	}

	public void draw(Graphics2D g2d) {
		g2d.setColor(Color.black);
		g2d.setStroke(new BasicStroke(Math.abs(densidadeCarga)));

		g2d.drawLine(Math.round(p0[0]),
						Math.round(p0[1]),
						Math.round(p1[0]),
						Math.round(p1[1]));
		g2d.setStroke(new BasicStroke(1.0f));
	}
}
